﻿using System;
using System.Collections;
using System.Collections.Generic;
using RenderingPractice;
using UnityEngine;

[ExecuteInEditMode,ImageEffectAllowedInSceneView]
public class BloomPostEffect : PostEffectsBase
{
    const int BoxDownPreFliterPassId = 0;
    const int BoxDownPassId = 1;
    const int BoxUpPassId = 2;
    const int ApplyBloomPass = 3;
    const int DebugBloomPass = 4;

    [Header("强度"),Range(0,10)]
    public float Intensity = 1.0f;
    
    [Header("迭代次数"),Range(0,16)]
    public int Iterations = 1;

    [Header("亮度阈值"),Range(0,10)]
    public float Threshold = 1;
    [Header("平滑亮度阈值"),Range(0,1)]
    public float SoftThreshold = 0.5f;

    public bool DebugMode;

    public Shader BloomEffectShader;
    
    private Material mBloomMat;

    public Material BloomMat
    {
        get
        {
            mBloomMat = CheckShaderAndCreateMaterial(BloomEffectShader, mBloomMat);
            return mBloomMat;
        }
    }
    
    //*
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (BloomMat != null)
        {
            float knee = Threshold * SoftThreshold;
            Vector4 filterParam;
            filterParam.x = Threshold;
            filterParam.y = filterParam.x - knee;
            filterParam.z = 2f * knee;
            filterParam.w = 0.25f / (knee + 0.00001f);
            BloomMat.SetVector("_FilterParam", filterParam);
            BloomMat.SetFloat("_Intensity", Mathf.GammaToLinearSpace(Intensity));
            
            
            int width = src.width / 2;
            int height = src.height / 2;
            RenderTextureFormat format = src.format;
        
            RenderTexture[] textures = new RenderTexture[16];
        
            //获取临时RT，不使用深度缓冲
            RenderTexture curDest = textures[0] = RenderTexture.GetTemporary(width, height, 0,format);
        
            Graphics.Blit(src, curDest, BloomMat, BoxDownPreFliterPassId); //像素减半

            RenderTexture curSrc = curDest;

            int i = 1;
            for (; i <= Iterations; i++) //降采样
            {
                width /= 2;
                height /= 2;

                if (height < 2) break;
            
                curDest = textures[i] = RenderTexture.GetTemporary(width, height, 0,format);
            
                Graphics.Blit(curSrc, curDest, BloomMat, BoxDownPassId); //像素减半
            
                //RenderTexture.ReleaseTemporary(curSrc); //释放临时RT

                curSrc = curDest;
            }

            i -= 2;
            for (; i >= 0; i--) //升采样
            {
                curDest = textures[i];
                textures[i] = null;
                Graphics.Blit(curSrc, curDest, BloomMat, BoxUpPassId); //像素加倍
                RenderTexture.ReleaseTemporary(curSrc); //释放临时RT
                curSrc = curDest;
            }

            if (DebugMode)
            {
                Graphics.Blit(curSrc, dest, BloomMat, ApplyBloomPass);
            }
            else
            {
                BloomMat.SetTexture("_SourceTex", src);
                Graphics.Blit(curSrc, dest, BloomMat, ApplyBloomPass);
            }
        
            //释放临时RT
            RenderTexture.ReleaseTemporary(curSrc);
        }
        else
        {
            Graphics.Blit(src, dest);
        }
    }
    //*/   
       
    /*
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (BloomMat != null && Iterations > 0)
        {
            int width = src.width / 2;
            int height = src.height / 2;
            RenderTextureFormat format = src.format;
        
            RenderTexture[] textures = new RenderTexture[16];
        
            //获取临时RT，不使用深度缓冲
            RenderTexture curDest = textures[0] = RenderTexture.GetTemporary(width, height, 0,format);
        
            Graphics.Blit(src, curDest, BloomMat, BoxDownPassId); //像素减半

            RenderTexture curSrc = curDest;

            if (Iterations > 1)
            {
                int i = 2;
                for (; i <= Iterations; i++) //降采样
                {
                    width /= 2;
                    height /= 2;

                    if (height < 2) break;
            
                    curDest = textures[i-1] = RenderTexture.GetTemporary(width, height, 0,format);
            
                    Graphics.Blit(curSrc, curDest, BloomMat, BoxDownPassId); //像素减半
            
                    //RenderTexture.ReleaseTemporary(curSrc); //释放临时RT

                    curSrc = curDest;
                }

                if (Iterations > 2)
                {
                    i -= 2;
                    for (; i >= 1; i--) //升采样
                    {
                        curDest = textures[i-1];
                        textures[i-1] = null;
                        Graphics.Blit(curSrc, curDest, BloomMat, BoxUpPassId); //像素加倍
                        RenderTexture.ReleaseTemporary(curSrc); //释放临时RT
                        curSrc = curDest;
                    }
                }
            }
            BloomMat.SetTexture("_SourceTex", src);
            
            Graphics.Blit(curSrc, dest, BloomMat, ApplyBloomPass);
        
            //释放临时RT
            RenderTexture.ReleaseTemporary(curSrc);
        }
        else
        {
            Graphics.Blit(src, dest);
        }
    }
    //*/
}
